using UnityEngine;
using System.Collections.Generic;
using ClipperLib;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.IO;
using System.Collections;
using System.Linq;
using System;
using Unity.VisualScripting;

public class Game : MonoBehaviour
{
    public static Game Instance { get; private set; }

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            //DontDestroyOnLoad(gameObject);
        }
        else
        {
            // 如果重复出现了这个实例，就销毁这个对象
            Destroy(gameObject);
        }
    }

    /// <summary>
    /// 数据相关
    /// </summary>

    // 请将你要生成的预制体拖到 Inspector 中的这个变量上
    public GameObject prefab;

    // 进度条
    public Slider slider;
    public Slider sliderTarget;

    // 不规则多边形 填充对象
    public GameObject irregularShapeObject;
    // 存储不规则多边形数据
    private List<IntPoint> mainPolygon;

    // 人类 小块的名字集合
    public string[] humanPrefabNames = { "Square(Clone)", "Triangle(Clone)", "Circle(Clone)" };

    // 生成区域物体名字
    public string[] clickFieldNames = { "ClickField" };

    // 实例合集
    private List<GameObject> humanPrefabObject = new List<GameObject>();

    // 保存上一次的百分比
    private float previousPercentage = -1f;

    public GameObject HumanPool;

    // 关卡数据
    LevelData levelData;

    // 关卡信息
    public Text textLevelInfo;

    // 剩余人口数
    public int humanLeft = 0;

    public enum SpecialLevelStage
    {
        Stage1,
        Stage2,
        Stage3,
        Stage4,
        Stage5
    }

    public SpecialLevelStage currentStage = SpecialLevelStage.Stage1;

    /// <summary>
    /// 逻辑相关
    /// </summary>

    // 最后物体的静止时间
    GameObject lastHuman;
    Vector3 lastPosition = Vector3.zero;
    float timeCount = 3.0f;
    float timeRecord = 0f;
    float moveLimit = 1f;

    bool isCountingDown = false;
    public Text TimeCount;

    // 关卡准备完成
    bool isReady = false;

    void Start()
    {
        // 第一次进入 关卡ID为1 TODO
        DataManager.Level = 10;

        InitGame();
    }

    void Update()
    {
        // 只有准备好之后才会开始循环检测
        if (!isReady)
        {
            return;
        }

        // 检测鼠标左键点击事件
        if (Input.GetMouseButtonDown(0))
        {
            // 检查是否点击了 UI
            PointerEventData pointerData = new PointerEventData(EventSystem.current)
            {
                position = Input.mousePosition
            };

            // 检查是否还有人类剩余
            if (humanLeft <= 0 && !DataManager.IsSpecialLevel())
            {
                return;
            }

            List<RaycastResult> results = new List<RaycastResult>();
            EventSystem.current.RaycastAll(pointerData, results);

            // 遍历所有检测到的 UI 元素
            foreach (RaycastResult result in results)
            {
                // 检查 UI 名字是否在允许的列表中
                if (System.Array.Exists(clickFieldNames, name => name == result.gameObject.name))
                {
                    // 在点击位置生成预制体
                    Vector3 worldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                    worldPosition.z = 0; // 确保在 2D 平面上
                    lastHuman = Instantiate(prefab, worldPosition, Quaternion.identity, HumanPool.transform);

                    // 记录人类位置
                    lastPosition = lastHuman.transform.position;

                    // 创建了人类
                    if (DataManager.IsSpecialLevel())
                    {
                        humanLeft++;
                    }
                    else
                    {
                        humanLeft--;
                    }
                    // 刷新剩余人类数量
                    GameUI.Instance.RefreshHumanInfo();

                    // TODO 测试代码
                    //Debug.Log("改变播放内容为 bgm2");
                    //AudioManager.Instance.ChangeEndAction(()=> {
                    //    AudioManager.Instance.PlayBGM("BGM/Walkuerenritt_02", false);
                    //});


                    Debug.Log($"点击了允许的 UI 元素：{result.gameObject.name}");
                    return; // 只处理第一个匹配的 UI 元素
                }
            }

            Debug.Log("点击的 UI 不在允许的名字列表中");
        }

        if (DataManager.IsSpecialLevel())
        {
            return;
        }

        // 从场景中动态获取所有小方块的边界
        FetchHumanFromNames();

        mainPolygon = ConvertToClipperPath(irregularShapeObject.GetComponent<PolygonCollider2D>().points, irregularShapeObject.GetComponent<PolygonCollider2D>().transform);

        if (mainPolygon == null || mainPolygon.Count == 0)
            return;

        Clipper clipper = new Clipper();
        clipper.StrictlySimple = true;
        clipper.PreserveCollinear = true;
        float filledArea = 0f;

        int i = 0;

        foreach (GameObject obj in humanPrefabObject)
        {
            i++;

            BoxCollider2D smallSquareCollider = obj.GetComponent<BoxCollider2D>();
            Vector2 size = smallSquareCollider.size * obj.transform.lossyScale;
            Vector2 position = obj.transform.position;

            Rect rect = new Rect(
                position.x - size.x / 2,
                position.y - size.y / 2,
                size.x,
                size.y
            );

            List<IntPoint> smallPolygon = ConvertToClipperPath(RectToPolygon(rect));
            List<List<IntPoint>> intersection = new List<List<IntPoint>>();

            clipper.Clear();
            clipper.AddPath(mainPolygon, PolyType.ptSubject, true);
            clipper.AddPath(smallPolygon, PolyType.ptClip, true);

            clipper.Execute(ClipType.ctIntersection, intersection);

            if (intersection.Count == 0)
            {
                // 如果未闭合，请补充闭合逻辑：
                if (!mainPolygon[0].Equals(mainPolygon[mainPolygon.Count - 1]))
                {
                    mainPolygon.Add(mainPolygon[0]); // 闭合多边形
                }
            }
            else
            {
                foreach (var path in intersection)
                {
                    filledArea += CalculatePolygonArea(path);
                }
            }
        }

        float totalArea = CalculatePolygonArea(mainPolygon);
        float fillPercentage = (filledArea / totalArea) * 100f;

        // 是否通过检测
        bool isPass = false;
        // 最后的对象3秒内移动没有超过规定距离
        if (lastHuman != null)
        {
            // 说明逻辑：
            // 最后的对象距离上次记录的位置距离超过了moveLimit
            if (Vector3.Distance(lastHuman.transform.position, lastPosition) > moveLimit)
            {
                lastPosition = lastHuman.transform.position;
                timeRecord = 0f; // 重置计时器

                // 关闭倒计时
                StopCoroutine(CountdownCoroutine());
                isCountingDown = false;
                TimeCount.text = ""; // 清空文本
            }
            // 说明逻辑
            // 虽然没移动超过距离，但是还得判断是不是3秒了
            else
            {
                timeRecord += Time.deltaTime;
                // 说明逻辑
                // 这里面才是3秒了还没移动
                if (timeRecord >= timeCount)
                {
                    timeRecord = 0f;
                    lastHuman = null;
                    isPass = true; // 通过检测

                    // TODO 因为不需要大范围了，所以不再需要镜头控制
                    // 相机控制
                    /*
                    {
                        float maxY = float.MinValue;
                        Transform highestChild = null;

                        foreach (Transform child in HumanPool.transform) // 遍历所有子对象
                        {
                            if (child.position.y > maxY)
                            {
                                maxY = child.position.y;
                                highestChild = child; // 记录最高的子对象
                            }
                        }
                        if (highestChild != null)
                        {
                            maxY = maxY / 0.618f;
                            //Debug.Log("Y 最大的子对象是：" + highestChild.name + "，坐标：" + maxY);
                            // 0.618 好像是相机部分有点小问题，修正一下
                            CameraControl.Instance.upperObjectPosition.y = maxY > 10 ? maxY : 10.0f;
                        }
                    }
                     */
                }
                // 开始检测现实倒计时
                if (fillPercentage >= levelData.completionPercentage)
                {
                    if (!isCountingDown) // 防止重复启动协程
                    {
                        StartCoroutine(CountdownCoroutine());
                        isCountingDown = true;
                    }
                }
                else if (humanLeft <= 0)
                {
                    if (!isCountingDown) // 防止重复启动协程
                    {
                        StartCoroutine(CountdownCoroutine());
                        isCountingDown = true;
                    }
                }
                else
                {
                    StopCoroutine(CountdownCoroutine());
                    isCountingDown = false;
                    TimeCount.text = ""; // 清空文本
                }
            }
        }

        if (!Mathf.Approximately(fillPercentage, previousPercentage))
        {
            previousPercentage = fillPercentage;
            Debug.Log($"填充百分比：{fillPercentage}%");

            slider.value = fillPercentage / 100.0f;

            // sliderTarget滑块颜色根据填充情况改变颜色
            if (fillPercentage >= levelData.completionPercentage)
            {
                sliderTarget.targetGraphic.GetComponent<Image>().color = Color.green;
            }
            else
            {
                sliderTarget.targetGraphic.GetComponent<Image>().color = Color.red;
            }
        }

        // 如果没通过3秒检测 先拦截
        if (!isPass)
        {
            return;
        }
        // 在停止变动一段时间之后给出结果
        if (fillPercentage >= levelData.completionPercentage)
        {
            // 如果已经是最后一关 TODO 暂时9关
            //if (DataManager.Level >= 10)
            //{
            //    Clear();
            //    return;
            //}

            Win();
            return;
        }
        // 如果人类资源用完了    
        if (humanLeft <= 0)
        {
            Lose();
            return;
        }
    }

    private IEnumerator CountdownCoroutine()
    {
        int countdown = 3; // 从 3 开始倒计时
        while (countdown > 0)
        {
            TimeCount.text = countdown.ToString(); // 更新 Text 组件
            yield return new WaitForSeconds(1f); // 等待 1 秒
            countdown--;
        }

        TimeCount.text = ""; // 倒计时结束后清空文本

        // 倒计时结束后执行逻辑
        //if (humanLeft <= 0)
        //{
        //    Lose(); // 如果人类数量为 0，则失败
        //}
        //else if (previousPercentage >= levelData.completionPercentage)
        //{
        //    Win(); // 如果填充比例满足条件，则胜利
        //}
    }

    // 初始化游戏
    void InitGame()
    {
        // 读取关卡数据
        levelData = Resources.Load<LevelData>("LevelData/LevelData" + DataManager.Level);

        // 关卡重置
        Reset();

        // 初始化镜头位置 因为高度没有正相关 计算不好用，得用配置
        //float posY = levelData.imageYScale / 0.618f;
        float posY = levelData.cameraValue;
        CameraControl.Instance.upperObjectPosition.y = posY < 10 ? 10 : posY;
        Debug.Log("镜头位置调整到：" + CameraControl.Instance.upperObjectPosition.y);

        // 刷新人类信息
        GameUI.Instance.RefreshHumanInfo();
        textLevelInfo.text = levelData.completionMessage;
        // 初始化目标百分比横线
        sliderTarget.value = levelData.completionPercentage / 100.0f;
        // 初始化剩余人类数量
        humanLeft = levelData.availableHumans;

        // 特殊关卡检测
        if (DataManager.IsSpecialLevel())
        {
            // TODO 特殊关卡演出
            // 修改信息
            GameUI.Instance.ChangeHumanInfo("投入人口：");
            // 重置相机
            CameraControl.Instance.targetPos = new Vector3(0, 10.691f, -10);
            Camera.main.orthographicSize = 10.691f;
            // 隐藏两个按钮
            // 右上角显示内容变更
            GameUI.Instance.SpecialLevelInit();
            // 镜头移动开启
            // 开始播放BGM
            AudioManager.Instance.PlayBGM("BGM/Walkuerenritt_01", false);
            AudioManager.Instance.ChangeEndAction(() =>
            {
                AudioManager.Instance.PlayBGM("BGM/Walkuerenritt_01", false);
            });
            isReady = true;
            return;
        }

        // 初始化多边形
        irregularShapeObject.GetComponent<PolygonCollider2D>().points = levelData.polygonPoints.ToArray();
        // 多边形位置
        irregularShapeObject.transform.position = new Vector3(levelData.xPos, levelData.yPos, 0);
        // 多边形子对象spriterenderer的sprite
        SpriteRenderer[] spriteRenderers = irregularShapeObject.GetComponentsInChildren<SpriteRenderer>();
        if (spriteRenderers.Length > 0)
        {
            string imagePath = levelData.imagePath;
            // 图片路径 剔除 后缀和Asset/Resources Resources之后的路径和文件名
            imagePath = "Image/" + Path.GetFileNameWithoutExtension(imagePath);
            if (!string.IsNullOrEmpty(imagePath))
            {
                // 加载图片资源
                Texture2D texture = Resources.Load<Texture2D>(imagePath);
                if (texture != null)
                {
                    spriteRenderers[0].sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
                    //spriteRenderers[0].transform.localScale = new Vector3(levelData.imageXScale, levelData.imageYScale, 1);
                    spriteRenderers[0].size = new Vector2(levelData.imageXScale, levelData.imageYScale);
                }
                else
                {
                    Debug.LogError("未找到图片资源：" + imagePath);
                }
            }
        }

        // 检索不规则多边形的点并转换为 Clipper 格式
        if (irregularShapeObject != null)
        {
            mainPolygon = ConvertToClipperPath(irregularShapeObject.GetComponent<PolygonCollider2D>().points, irregularShapeObject.GetComponent<PolygonCollider2D>().transform);
        }
        else
        {
            Debug.LogError("请为不规则图形设置 PolygonCollider2D！");
        }

        isReady = true;
    }

    // 第二阶段 7s
    public void InitGameStage2()
    {
        currentStage = SpecialLevelStage.Stage2;
        AudioManager.Instance.ChangeEndAction(() =>
        {
            AudioManager.Instance.PlayBGM("BGM/Walkuerenritt_02", false);
            // 2秒后执行后续代码
            StartCoroutine(DelayedAction(1.0f, () =>
            {
                InitGameStage3();
            }));
        });
        // 显示文字 提示不需要继续操作 进入自动流程
        // 云层突破
        // 隐藏只能点击这里
        // 改变为显示抽象人塔
    }

    // 第三阶段
    void InitGameStage3()
    {
        // 云层逐渐下降
        currentStage = SpecialLevelStage.Stage3;
        AudioManager.Instance.ChangeEndAction(() =>
        {
            AudioManager.Instance.PlayBGM("BGM/Walkuerenritt_03", false);
            // 2秒后执行后续代码
            StartCoroutine(DelayedAction(1.0f, () =>
            {
                InitGameStage4();
            }));
        });
        // 天空盒开始变暗最后变成纯黑
    }

    void InitGameStage4()
    {
        currentStage = SpecialLevelStage.Stage4;
        AudioManager.Instance.ChangeEndAction(() =>
        {
            AudioManager.Instance.PlayBGM("BGM/Walkuerenritt_04", false);
            // 2秒后执行后续代码
            StartCoroutine(DelayedAction(1.0f, () =>
            {
                InitGameStage5();
            }));
        });
        // 出现星星
    }

    void InitGameStage5()
    {
        currentStage = SpecialLevelStage.Stage5;
        AudioManager.Instance.ChangeEndAction(() =>
        {
            AudioManager.Instance.PlayBGM("BGM/Walkuerenritt_05", false);
            StartCoroutine(DelayedAction(1.0f, () =>
            {
                // 关闭后续事件
                AudioManager.Instance.ChangeEndAction(() => { });
            }));
        });
        // 在指定时间出现月球
        // 设置倒计时
        StartCoroutine(DelayedAction(35.0f, Clear));
    }

    IEnumerator DelayedAction(float time, Action delayAction)
    {
        yield return new WaitForSeconds(time); // 等待 0.1 秒
        // 停止背景滚动
        // 人数增加到80亿结束
        // 结束游戏
        delayAction();
    }

    // 更新特殊关卡百分比
    public void RefreshSpecialLevel(float num)
    {
        switch (currentStage)
        {
            case SpecialLevelStage.Stage1:
                slider.value = num / 100.0f * 0.1f;
                break;
            case SpecialLevelStage.Stage2:
                break;
            case SpecialLevelStage.Stage3:
                break;
            case SpecialLevelStage.Stage4:
                break;
            case SpecialLevelStage.Stage5:
                break;
            default:
                break;
        }
    }
    // 游戏胜利 达到目标填充百分比
    void Win()
    {
        isReady = false;

        // 显示胜利界面
        PopWindowOne.Instance.Show("过关！", () =>
        {
            // 关卡ID变化
            DataManager.Level++;
            // 初始化关卡
            InitGame();
            // 打印关卡ID
            Debug.Log("当前关卡ID是：" + DataManager.Level);
        });
    }

    // 游戏失败 角色资源使用完毕 未能达到目标填充百分比
    void Lose()
    {
        // 显示失败界面
        PopWindowOne.Instance.Show("该罚！", () =>
        {
            // 初始化关卡
            InitGame();
            // 打印关卡ID
            Debug.Log("当前关卡ID是：" + DataManager.Level);
        });
    }

    // 游戏通关
    void Clear()
    {
        isReady = false;
        // 显示失败界面
        PopWindowOne.Instance.Show("恭喜通关！", () =>
        {
            //返回主菜单
            GameSceneManager.Instance.LoadContentScene("StartScene");
        });
    }

    // 退回主界面
    public void Quit()
    {
        isReady = false;
        // 弹出二级菜单
        PopWindowTwo.Instance.Show(
            "要退出到主界面吗？",
            () =>
            {
                //返回主菜单
                GameSceneManager.Instance.LoadContentScene("StartScene");
            },
            () => { }
        );
    }

    // 重置游戏状态
    public void Reset()
    {
        slider.value = 0;
        previousPercentage = -1f;
        // 重置人数
        humanLeft = levelData.availableHumans;
        GameUI.Instance.RefreshHumanInfo();
        // 清空小方块列表
        foreach (GameObject square in humanPrefabObject)
        {
            Destroy(square);
        }
    }

    // 根据名字查找场景中的小方块并获取边界
    void FetchHumanFromNames()
    {
        humanPrefabObject.Clear();

        foreach (string squareName in humanPrefabNames)
        {
            // 获取场景中所有的 GameObject
            GameObject[] allObjects = FindObjectsOfType<GameObject>();

            // 遍历并找到名字为 "abc" 的物体
            foreach (GameObject obj in allObjects)
            {
                if (obj.name == squareName)
                {
                    BoxCollider2D collider = obj.GetComponent<BoxCollider2D>();
                    if (collider != null)
                    {
                        humanPrefabObject.Add(obj);
                    }
                    else
                    {
                        Debug.LogWarning($"未找到 BoxCollider2D：{squareName}");
                    }
                }
            }
        }
    }

    // 将 Rect 转换为多边形的点列表
    Vector2[] RectToPolygon(Rect rect, Transform transform = null)
    {
        Vector2[] points = new Vector2[]
        {
        new Vector2(rect.xMin, rect.yMin),
        new Vector2(rect.xMax, rect.yMin),
        new Vector2(rect.xMax, rect.yMax),
        new Vector2(rect.xMin, rect.yMax)
        };

        // 如果有 transform，将每个点转换为世界坐标
        if (transform != null)
        {
            for (int i = 0; i < points.Length; i++)
            {
                points[i] = transform.TransformPoint(points[i]);
            }
        }

        return points;
    }

    // 将 三角形 转换为多边形的点列表
    Vector2[] TriangleToPolygon(Vector2 center, float size, Transform transform = null)
    {
        Vector2[] points = new Vector2[3];
        float angle = 0f;

        for (int i = 0; i < 3; i++)
        {
            points[i] = new Vector2(
                center.x + size * Mathf.Cos(angle),
                center.y + size * Mathf.Sin(angle)
            );
            angle += 2 * Mathf.PI / 3; // 每次增加120度
        }

        // 如果有 transform，将每个点转换为世界坐标
        if (transform != null)
        {
            for (int i = 0; i < points.Length; i++)
            {
                points[i] = transform.TransformPoint(points[i]);
            }
        }

        return points;
    }

    // 将 圆形 转换为多边形的点列表
    Vector2[] CircleToPolygon(Vector2 center, float radius, int segmentCount = 36, Transform transform = null)
    {
        Vector2[] points = new Vector2[segmentCount];
        float angleStep = 2 * Mathf.PI / segmentCount;

        for (int i = 0; i < segmentCount; i++)
        {
            float angle = i * angleStep;
            points[i] = new Vector2(
                center.x + radius * Mathf.Cos(angle),
                center.y + radius * Mathf.Sin(angle)
            );
        }

        // 如果有 transform，将每个点转换为世界坐标
        if (transform != null)
        {
            for (int i = 0; i < points.Length; i++)
            {
                points[i] = transform.TransformPoint(points[i]);
            }
        }

        return points;
    }

    // 转换 Unity 的 Vector2 点到 Clipper 的 IntPoint
    List<IntPoint> ConvertToClipperPath(Vector2[] points, Transform transform = null)
    {
        List<IntPoint> clipperPath = new List<IntPoint>();
        const int scaleFactor = 1000; // 可根据实际需要调整比例

        foreach (var point in points)
        {
            Vector2 worldPoint = point;

            // 如果有 transform，则将局部坐标转换为世界坐标
            if (transform != null)
            {
                worldPoint = transform.TransformPoint(point);
            }

            clipperPath.Add(new IntPoint(
                Mathf.RoundToInt(worldPoint.x * scaleFactor),
                Mathf.RoundToInt(worldPoint.y * scaleFactor)
            ));
        }
        return clipperPath;
    }

    // 收束坐标范围
    public static List<IntPoint> ScalePolygon(List<IntPoint> myPolygon)
    {
        // 获取最大坐标值
        long maxX = myPolygon.Max(pt => Mathf.Abs(pt.X));
        long maxY = myPolygon.Max(pt => Mathf.Abs(pt.Y));
        long maxCoord = Math.Max(maxX, maxY);

        // 计算缩放比例
        float scaleFactor = 32767f / maxCoord;

        // 归一化缩放
        return myPolygon.Select(pt =>
            new IntPoint((long)(pt.X * scaleFactor), (long)(pt.Y * scaleFactor))
        ).ToList();
    }

    // 2收1
    public static void ScalePolygons(ref List<IntPoint> poly1, ref List<IntPoint> poly2)
    {
        // 1. 计算两个列表中的最大坐标值
        long maxX1 = poly1.Max(pt => Mathf.Abs(pt.X));
        long maxY1 = poly1.Max(pt => Mathf.Abs(pt.Y));

        long maxX2 = poly2.Max(pt => Mathf.Abs(pt.X));
        long maxY2 = poly2.Max(pt => Mathf.Abs(pt.Y));

        long maxCoord = Math.Max(Math.Max(maxX1, maxY1), Math.Max(maxX2, maxY2)); // 选取最大坐标值

        // 2. 计算统一的缩放比例
        float scaleFactor = 32767f / maxCoord; // 让所有点缩放到范围内

        // 3. 应用缩放
        poly1 = poly1.Select(pt => new IntPoint((long)(pt.X * scaleFactor), (long)(pt.Y * scaleFactor))).ToList();
        poly2 = poly2.Select(pt => new IntPoint((long)(pt.X * scaleFactor), (long)(pt.Y * scaleFactor))).ToList();
    }

    // 计算多边形的面积
    float CalculatePolygonArea(List<IntPoint> points)
    {
        double area = 0;
        int count = points.Count;

        for (int i = 0; i < count; i++)
        {
            IntPoint current = points[i];
            IntPoint next = points[(i + 1) % count];
            area += (current.X * next.Y) - (next.X * current.Y);
        }

        return Mathf.Abs((float)(area / 2.0)) / (10000 * 10000); // 转换回浮点数面积
    }
}
